package lew.bing.exp.collection;


import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * Created by 刘国兵 on 2018/9/1.
 */
public class ListUtils {


    public static <R> ArrayList<R> newArrayList(R... elements) {
        ArrayList<R> objects = new ArrayList<>();
        if (elements == null) {
            return objects;
        }
        objects.addAll(Arrays.asList(elements));
        return objects;
    }

    public static boolean isEmpty(List<?> from) {
        return from == null || from.isEmpty();
    }

    public static boolean isNotEmpty(List<?> from) {
        return ! isEmpty(from);
    }

    public <R> R checkNull(R from) {
        if (from == null) {
            throw new NullPointerException();
        }
        return from;
    }

    public static <T,R> List<T> transform(List<R> from, Function<R,T> transfer) {
        if (from instanceof RandomAccess) {
            return new TransformList<>(from,transfer);
        }
        return new TransformSequentialList<>(from,transfer);
    }

    private static class TransformSequentialList<T,R> extends AbstractSequentialList<T> {

        private List<R> from;
        private Function<R,T> transfer;

        public TransformSequentialList(List<R> from, Function<R, T> transfer) {
            this.from = from;
            this.transfer = transfer;
        }

        @Override
        public ListIterator<T> listIterator(int index) {
            return new TransferIterator<>(from.listIterator(index)) {

                @Override
                protected T transfer(R r) {
                    return transfer.apply(r);
                }
            };
        }

        @Override
        public int size() {
            return from.size();
        }

        @Override
        public boolean removeIf(Predicate<? super T> filter) {
            return from.removeIf(r -> filter.test(transfer.apply(r)));
        }



    }

    private static class TransformList<T,R> extends AbstractList<T> {

        private List<R> from;
        private Function<R,T> transfer;

        public TransformList(List<R> from, Function<R, T> transfer) {
            this.from = from;
            this.transfer = transfer;
        }

        @Override
        public T get(int index) {
            return transfer.apply(from.get(index));
        }

        @Override
        public int size() {
            return from.size();
        }

        @Override
        public boolean removeIf(Predicate<? super T> filter) {
            return from.removeIf(r -> filter.test(transfer.apply(r)));
        }

        @Override
        public T remove(int index) {
            return transfer.apply(from.remove(index));
        }

        @Override
        public Iterator<T> iterator() {
            return listIterator();
        }

        @Override
        public ListIterator<T> listIterator(int index) {
            return new TransferIterator<>(from.listIterator(index)) {

                @Override
                protected T transfer(R r) {
                    return transfer.apply(r);
                }
            };
        }

        @Override
        public void clear() {
            from.clear();
        }
    }

}
